home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 426-450 / disk_450 / uucp / src / getty / getty.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  22KB  |  1,122 lines

  1.  
  2. /*
  3.  *  GETTY.C
  4.  *
  5.  *  $Header: Beta:src/uucp/src/getty/RCS/getty.c,v 1.1 90/02/02 12:13:30 dillon Exp Locker: dillon $
  6.  *
  7.  *  (C)Copyright 1989, Matthew Dillon, All Rights Reserved
  8.  *
  9.  *  Uses:
  10.  *    GETTY:PASSWD
  11.  *    GETTY:LOGFILE
  12.  *    GETTY:Getty-Header
  13.  *
  14.  *  GETTY   <options>    <modem-commands>
  15.  *
  16.  *    -Sdevicenam Tells GETTY which serial.device to use, default
  17.  *            serial.device
  18.  *
  19.  *    -Uunitnum   Tells GETTY which unit number to use, default 0
  20.  *
  21.  *    -A        Always talk to the modem at the first baud
  22.  *            rate in the -B list and ignore the baud rate
  23.  *            in the CONNECT message.
  24.  *
  25.  *    -7        use SERF_7WIRE while online.
  26.  *
  27.  *    -Bn        Set baud rate.  If specified multiple times the
  28.  *            first one is the default and remaining ones
  29.  *            switched to when a BREAK is received after a
  30.  *            connect.  Also determines how CONNECT messages
  31.  *            are interpreted.  A CONNECT with no number uses
  32.  *            the first -B entry while CONNECTs with numbers
  33.  *            use those numbers regardless of any -B entries.
  34.  *
  35.  *    -Mc        Set modem type:
  36.  *            c = m    = multimodem
  37.  *                h    = hays
  38.  *                d    = dumb (no AT or +++ cmds are ever sent),
  39.  *                  normally used with only one specified
  40.  *                  baud rate.
  41.  *
  42.  *    -m1        Turn on the modem speaker during dialing/connect
  43.  *            (default is -m0)
  44.  *
  45.  *    -h0        Ignore CD (carrier detect), default is to use
  46.  *            carrier detect.
  47.  *
  48.  *    -c0        Ignore CONNECT message (i.e. you are not connected
  49.  *            to a modem, usually combined with -h0).  Default is
  50.  *            to expect a CONNECT message.
  51.  *
  52.  *    -d0        do not use DTR to drop connection.    Default is
  53.  *            to drop DTR to drop a connection.  If this option
  54.  *            is chosen the +++ and ATH0 sequence will be used
  55.  *            to drop a connection.
  56.  *
  57.  *    -xn        Set debug level.  Also causes log output to go
  58.  *            to stdout instead of GETTY:LOGFILE
  59.  *
  60.  *    -0        QUIT - Kills any running getty for the specified
  61.  *            port.
  62.  *
  63.  *    Any fields specified without a '-' are considered modem commands
  64.  *    used to initialize/reinitialize the modem.  Up to 16 fields may
  65.  *    be specified (each is sent to the modem in 1 second intervals)
  66.  */
  67.  
  68. #include <exec/types.h>
  69. #include <exec/lists.h>
  70. #include <exec/devices.h>
  71. #include <exec/io.h>
  72. #include <devices/timer.h>
  73. #include <devices/serial.h>
  74. #include <libraries/dos.h>
  75. #include <libraries/dosextens.h>
  76. #include <hardware/cia.h>
  77. #include <stdio.h>
  78. #include <stdlib.h>
  79. #include "protos.h"
  80. #include <pwd.h>
  81. #include "version.h"
  82.  
  83. #include "log.h"
  84.  
  85. IDENT(".06");
  86.  
  87. #ifndef IO_STATF_READBREAK
  88. #define IO_STATF_READBREAK (IOSTF_READBREAK<<8)
  89. #endif
  90.  
  91. #define arysize(ary)    (sizeof(ary)/sizeof((ary)[0]))
  92.  
  93. #define ST_WAITCD    0
  94. #define ST_CONNECT    1
  95. #define ST_LOGIN    2
  96. #define ST_PASSWD    3
  97. #define ST_RUN        4
  98.  
  99. typedef struct IORequest    IOR;
  100. typedef struct timerequest  IOT;
  101. typedef struct IOExtSer     IOSER;
  102. typedef struct MsgPort        PORT;
  103. typedef struct List        LIST;
  104. typedef struct Node        NODE;
  105. typedef struct Message        MSG;
  106. typedef void (*FPTR)();
  107.  
  108. typedef struct GMsg {
  109.     struct Message  Msg;
  110.     short   Cmd;
  111.     long    Data1;
  112.     void    *Data2;
  113. } GMsg;
  114.  
  115. extern struct ProcID *RunPasswdEntry();
  116.  
  117. char    *CopyRight = "(c)Copyright 1989, Matthew Dillon, All Rights Reserved\r\n";
  118. char    *ComPortName;
  119.  
  120. char    *DeviceName = "serial.device";
  121. long    DeviceUnit  = 0;
  122. long    RefCnt        = 0;    /*  take into account ourselves    */
  123. long    NullFH;
  124. char    SpeakerLevel    = 0;
  125. char    AnswerRing    = 2;    /*  default, answer on second ring */
  126. char    SpeakerOpt    = 0;
  127. char    IgnoreCD    = 0;
  128. char    IgnoreConnect    = 0;
  129. char    IgnoreDTR    = 0;
  130. char    BaudAdjust    = 0;
  131. char    DropOnExit    = 1;
  132. char    ModemType    = 'h';
  133. char    ZeroOption    = 0;
  134. /*char      NoBugs      = 0;*/
  135. char    Wire7        = 0;        /*  use 7 wire while online */
  136. long    Bauds[16] = { 9600 };        /*  up 16 baud rates        */
  137. char    *AtFields[16];
  138. void    *GettyTask;
  139.  
  140. APTR    UnitPtr;
  141.  
  142. PORT    *ComPort;
  143. PORT    *IoSink;    /*  Sink for IO reqs.    */
  144. long    IoSinkMask;
  145. long    ComPortMask;
  146.  
  147. IOT    Iot;        /*  check-carrier    */
  148. IOSER    Ios;        /*  parameters req    */
  149. IOSER    Iosr;        /*  serial read-req    */
  150. IOSER    Ioss;        /*  synchronous req    */
  151.  
  152. char    IotIP;        /*  Iot0 in progress    */
  153. char    IosrIP;
  154.  
  155. char    ScrBuf[256];
  156. char    ConnectBuf[64];
  157. char    LoginBuf[32];
  158. char    PasswdBuf[32];
  159. char    RxBuf[32];
  160. char    HaveConnectMsg;
  161. char    HaveLogin;
  162. char    HavePasswd;
  163.  
  164. short    State;
  165. short    Index;
  166. short    BIndex;
  167.  
  168. short CountDown;
  169. short GotOffPort;
  170.  
  171. long    GetStatus();
  172. void    SerPuts();
  173. void    RxStop();
  174. void    RxStart();
  175. void    xexit();
  176. void    Disconnect();
  177. void    ClearRecv();
  178. void    ResetSP();
  179. void    InitModem();
  180. void    SetParams();
  181. void    DoOptions();
  182. void    InterceptDeviceVector();
  183. void    RestoreDeviceVector();
  184.  
  185. brk()
  186. {
  187.     return(0);
  188. }
  189.  
  190. main(ac, av)
  191. char *av[];
  192. {
  193.     extern int IAmGetty;
  194.     char termCr = 1;
  195.     char termLf = 1;
  196.  
  197.     IAmGetty = 1;    /*  for LockSerialPort()/UnLockSerialPort()   */
  198.  
  199.     puts(CopyRight);
  200.     fflush(stdout);
  201.     onbreak(brk);
  202.  
  203.     LogProgram = "Getty";
  204.     LogWho = LoginBuf;
  205.     LogFile = "Getty:LOGFILE";
  206.     PasswdFile = "Getty:Passwd";
  207.  
  208.     DoOptions(ac, av);
  209.  
  210.     IoSink = CreatePort(NULL, 0);
  211.     IoSinkMask = 1 << IoSink->mp_SigBit;
  212.  
  213.     ComPortName = malloc(strlen(DeviceName) + 20);
  214.     sprintf(ComPortName, "Getty.%s.%ld", DeviceName, DeviceUnit);
  215.  
  216.     Forbid();
  217.     if (ComPort = FindPort(ComPortName)) {
  218.     GMsg msg;
  219.     msg.Cmd = 'O';
  220.     msg.Data1 = ac;
  221.     msg.Data2 = (void *)av;
  222.     msg.Msg.mn_ReplyPort = IoSink;
  223.     PutMsg(ComPort, &msg.Msg);
  224.     WaitPort(IoSink);
  225.     Remove(&msg.Msg.mn_Node);
  226.     Permit();
  227.     puts("Options updated");
  228.     xexit(0);
  229.     }
  230.     ComPort = CreatePort(ComPortName, 0L);
  231.     Permit();
  232.  
  233.     ComPortMask = 1L << ComPort->mp_SigBit;
  234.  
  235.     NullFH = Open("NULL:", 1006);
  236.     if (NullFH == NULL) {
  237.     ulog(-1, "GETTY REQUIRES NULL: HANDLER!");
  238.     puts("Requires NULL: handler!");
  239.     xexit(1);
  240.     }
  241.     if (LogToStdout == 0) {
  242.     freopen("NULL:", "r", stdin);
  243.     freopen("NULL:", "w", stdout);
  244.     freopen("NULL:", "w", stderr);
  245.     }
  246.  
  247.     /*
  248.      *    Timer Device
  249.      */
  250.  
  251.     Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
  252.     if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0L)) {
  253.     Iot.tr_node.io_Device = NULL;
  254.     xexit(20);
  255.     }
  256.     Iot.tr_node.io_Command = TR_ADDREQUEST;
  257.  
  258.     /*
  259.      *    SERIAL.DEVICE
  260.      */
  261.  
  262.     Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
  263.     Ios.io_SerFlags = SERF_XDISABLED | SERF_SHARED;
  264.     if (Wire7)
  265.     Ios.io_SerFlags |= SERF_7WIRE;
  266.     if (OpenDevice(DeviceName, DeviceUnit, &Ios, 0L)) {
  267.     Ios.IOSer.io_Device = NULL;
  268.     xexit(21);
  269.     }
  270.  
  271.     InterceptDeviceVector(Ios.IOSer.io_Device);
  272.  
  273.     Iosr = Ios;
  274.     Ioss = Ios;
  275.  
  276.     Iosr.IOSer.io_Command = CMD_READ;
  277.     Ios.IOSer.io_Command = SDCMD_QUERY;
  278.     DoIO(&Ios);
  279.  
  280.     Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
  281.     Ios.io_ExtFlags = 0;
  282.     Ios.io_Baud = Bauds[0];
  283.     Ios.io_ReadLen = 8;
  284.     Ios.io_WriteLen = 8;
  285.     Ios.io_StopBits = 1;
  286.  
  287.     SetParams(0);
  288.  
  289.     /*
  290.      *    Run Operation
  291.      */
  292.  
  293.     State = ST_WAITCD;
  294.     Iot.tr_time.tv_secs = 1;
  295.     Iot.tr_time.tv_micro= 0;
  296.     IotIP = 1;
  297.     SendIO(&Iot);
  298.  
  299.     InitModem();
  300.  
  301.     GettyTask = FindTask(NULL);
  302.  
  303.     Signal(GettyTask, IoSinkMask);
  304.  
  305.     for (;;) {
  306.     long mask;
  307.     IOR  *ior;
  308.     GMsg *msg;
  309.     mask = Wait(SIGBREAKF_CTRL_C | IoSinkMask | ComPortMask);
  310.  
  311.     ulog(9, "State = %d %d %08lx %08lx", State, RefCnt, UnitPtr, Ios.IOSer.io_Unit);
  312.  
  313.     if (mask & SIGBREAKF_CTRL_C)
  314.         break;
  315.  
  316.     if (msg = (GMsg *)GetMsg(ComPort)) {
  317.         do {
  318.         switch(msg->Cmd) {
  319.         case 'O':
  320.             DoOptions(msg->Data1, msg->Data2);
  321.             break;
  322.         }
  323.         ReplyMsg((MSG *)msg);
  324.         if (ZeroOption)
  325.             xexit(0);
  326.         } while (msg = (GMsg *)GetMsg(ComPort));
  327.         if (State == ST_WAITCD && !GotOffPort)
  328.         Disconnect(0);
  329.     }
  330.  
  331.     while (ior = (IOR *)GetMsg(IoSink)) {
  332.         if (ior == (IOR *)&Iot) {
  333.         short diu;
  334.         long status;
  335.  
  336.         IotIP = 0;
  337.         Iot.tr_time.tv_secs = 1;
  338.         Iot.tr_time.tv_micro= 0;
  339.  
  340.         /*
  341.          *  If # of references for unit is > 1 then device
  342.          *  is in use.    When refs fall <= 1 then reset the
  343.          *  serial port.
  344.          */
  345.  
  346.         diu = DeviceInUse();
  347.         if (diu) {
  348.             if (GotOffPort == 0) {
  349.             ulog(1, "Device in use");
  350.             RxStop();
  351.             State = ST_WAITCD;
  352.             }
  353.             GotOffPort = 2;
  354.             SendIO(&Iot);
  355.             IotIP = 1;
  356.             continue;
  357.         }
  358.         if (GotOffPort) {
  359.             /*
  360.              *    delay 5 seconds before getting back on port
  361.              */
  362.  
  363.             if (--GotOffPort) {
  364.             Iot.tr_time.tv_secs = 5;
  365.             SendIO(&Iot);
  366.             IotIP = 1;
  367.             } else {
  368.             ulog(1, "Getty resetting");
  369.             SendIO(&Iot);
  370.             IotIP = 1;
  371.             Disconnect(1);
  372.             }
  373.             continue;
  374.         }
  375.         if (State == ST_WAITCD)
  376.             RxStop();
  377.  
  378.         if (State != ST_WAITCD && IosrIP == 0) {
  379.             RxStart();
  380.             ulog(2, "Carrier, Getty getting on port");
  381.         }
  382.  
  383.         status = GetStatus();
  384.  
  385.         /*
  386.          *  If state connected and we loose carrier, disconnect.
  387.          *
  388.          *  If state connected and timeout occurs disconnect.
  389.          */
  390.  
  391.         if (State != ST_WAITCD) {
  392.             if ((status & CIAF_COMCD) != 0) {
  393.             ulog(2, "Getty, Carrier lost");
  394.             Disconnect(1);
  395.             } else {
  396.             if (!IgnoreCD && --CountDown == 0) {
  397.                 ulog(2, "Getty, Timeout, Disconnecting");
  398.                 Disconnect(1);
  399.                 status |= CIAF_COMCD;   /*    set lost carrier flag */
  400.             }
  401.             }
  402.         }
  403.  
  404.         switch(State) {
  405.         case ST_WAITCD:
  406.             if ((status & CIAF_COMCD) == 0) {
  407.             State = ST_CONNECT;
  408.             CountDown = 60;     /*    allow 60 seconds */
  409.             ulog(2, "Carrier Detect");
  410.             } else {
  411.             Iot.tr_time.tv_secs = 2;
  412.             }
  413.             break;
  414.         case ST_CONNECT:
  415.             /*
  416.              *    Wait for CONNECT message, then send Login:
  417.              */
  418.  
  419.             if (IgnoreConnect && HaveConnectMsg == 0) {
  420.             SetParams(1);
  421.             HaveConnectMsg = 1;
  422.             ulog(2, "Connect");
  423.             }
  424.  
  425.             if (HaveConnectMsg) {
  426.             FILE *fi;
  427.  
  428.             Delay(50);
  429.             ClearRecv();
  430.             if (fi = fopen("Getty:Getty-Header", "r")) {
  431.                 while (fgets(ScrBuf, sizeof(ScrBuf), fi)) {
  432.                 SerPuts(ScrBuf);
  433.                 SerPuts("\r");
  434.                 }
  435.                 fclose(fi);
  436.             }
  437.             termCr = termLf = 1;
  438.             ClearRecv();
  439.             SerPuts("Login: ");
  440.             ulog(1, "Getty, Connect, Login");
  441.             State = ST_LOGIN;
  442.             Index = 0;
  443.             HaveLogin = 0;
  444.             LoginBuf[0] = 0;
  445.             }
  446.             break;
  447.         case ST_LOGIN:        /*    wait Login: response    */
  448.             if (HaveLogin) {
  449.             if (LoginBuf[0] == 0) {
  450.                 State = ST_CONNECT;
  451.                 break;
  452.             }
  453.             ClearRecv();
  454.             PasswdBuf[0] = 0;
  455.  
  456.             /*
  457.              *  If no password required, else request
  458.              *  password.
  459.              */
  460.  
  461.             if (CheckLoginAndPassword()) {
  462.                 HavePasswd = 1;
  463.                 Index = 0;
  464.                 State = ST_PASSWD;
  465.             } else {
  466.                 SerPuts("Password: ");
  467.                 ulog(2, "Getty, Passwd");
  468.                 State = ST_PASSWD;
  469.                 HavePasswd = 0;
  470.                 Index = 0;
  471.             }
  472.             }
  473.             break;
  474.         case ST_PASSWD:     /*    wait Password: response */
  475.             if (HavePasswd) {
  476.             if (CheckLoginAndPassword()) {
  477.                 ulog(-1, "login %s", LoginBuf);
  478.  
  479.                 /*
  480.                  *    Disable read requests but leave serial
  481.                  *    port locked.
  482.                  */
  483.  
  484.                 RxStop();
  485.  
  486.                 /*
  487.                  *    If run successful, leave read req and
  488.                  *    timer disabled.
  489.                  */
  490.  
  491.                 RunPasswdEntry();
  492.  
  493.                 if (DropOnExit)
  494.                 Disconnect(1);
  495.                 else
  496.                 State = ST_CONNECT;
  497.                 ulog(-1, "disconnect");
  498.             } else {
  499.                 SerPuts("Login Failed.\r\n\n");
  500.                 State = ST_CONNECT;
  501.                 ulog(0, "LoginFailed user=%s pass=%s", LoginBuf, PasswdBuf);
  502.             }
  503.             HaveLogin = 0;
  504.             HavePasswd= 0;
  505.             LoginBuf[0] = 0;
  506.             }
  507.             break;
  508.         }
  509.  
  510.         /*
  511.          *  Make no read requests while running 3rd party
  512.          *  program, else resend read request.
  513.          */
  514.  
  515.         if (IotIP == 0) {
  516.             IotIP = 1;
  517.             SendIO(&Iot);
  518.         }
  519.         }
  520.  
  521.         /*
  522.          *    RECEIVED SERIAL READ DATA
  523.          */
  524.  
  525.         if (ior == (IOR *)&Iosr) {
  526.         long status;
  527.  
  528.         IosrIP = 0;
  529.  
  530.         status = GetStatus();
  531.  
  532.         /*
  533.          *  BREAK used to switch baud rates between allowed
  534.          *  values
  535.          */
  536.  
  537.         if (status & IO_STATF_READBREAK) {
  538.             if (BaudAdjust == 0 && (State == ST_LOGIN || State == ST_PASSWD)) {
  539.             if (++BIndex == arysize(Bauds))
  540.                 BIndex = 0;
  541.             if (Bauds[BIndex] == 0)
  542.                 BIndex = 0;
  543.             Ios.io_Baud = Bauds[BIndex];
  544.             SetParams(1);
  545.             ulog(1, "<BREAK> to %d baud", Ios.io_Baud);
  546.             Delay(50);
  547.             ClearRecv();
  548.             Index = 0;
  549.             State = ST_CONNECT;
  550.             }
  551.         } else if (Iosr.IOSer.io_Actual == 1) {
  552.             char *ptr;
  553.             UBYTE c = (UBYTE)RxBuf[0];
  554.  
  555.             ulog(9, "Rx %02x %c", c, (c < 32) ? ' ' : c);
  556.             c &= 0x7F;
  557.  
  558.             switch(State) {
  559.             case ST_WAITCD:    /*  looking for CONNECT msg */
  560.             case ST_CONNECT:    /*  looking for CONNECT msg */
  561.             ptr = ConnectBuf;
  562.             break;
  563.             case ST_LOGIN:    /*  looking for login name  */
  564.             ptr = LoginBuf;
  565.             break;
  566.             case ST_PASSWD:    /*  looking for password    */
  567.             ptr = PasswdBuf;
  568.             break;
  569.             }
  570.             if (State == ST_LOGIN && HaveLogin)
  571.             c = 0;
  572.             if (State == ST_PASSWD && HavePasswd)
  573.             c = 0;
  574.  
  575.             switch(c) {
  576.             case 0:
  577.             break;
  578.             case 8:
  579.             if (State == ST_LOGIN && HaveLogin)
  580.                 break;
  581.             if (Index) {
  582.                 if (State == ST_LOGIN)
  583.                 SerPuts("\010 \010");
  584.                 --Index;
  585.             }
  586.             break;
  587.             case 10:
  588.             if (termLf == 0)
  589.                 break;
  590.             termCr = 0;
  591.             case 13:
  592.             if (c == 13) {
  593.                 if (termCr == 0)
  594.                 break;
  595.                 else
  596.                 termLf = 0;
  597.             }
  598.             ptr[Index] = 0;
  599.             Index = 0;
  600.             switch(State) {
  601.             case ST_WAITCD:
  602.             case ST_CONNECT:
  603.                 if (strncmp(ptr, "CONNECT", 7)) {
  604.                 ulog(9, "Looking for CONNECT, got '%s'", ptr);
  605.                 break;
  606.                 }
  607.                 Delay(50);
  608.                 HaveConnectMsg = 1;
  609.                 if (BaudAdjust) {
  610.                 ulog(9, "Connect Auto-Baud %d", Ios.io_Baud);
  611.                 } else {
  612.                 char *str = ptr + 7;
  613.                 while (*str && (*str == 9 || *str == ' '))
  614.                     ++str;
  615.                 if (*str >= '0' && *str <= '9')
  616.                     Ios.io_Baud = atoi(str);
  617.                 else
  618.                     Ios.io_Baud = Bauds[0];
  619.                 ulog(9, "Connect at %d baud", Ios.io_Baud);
  620.                 }
  621.                 SetParams(1);
  622.                 break;
  623.             case ST_LOGIN:
  624.                 HaveLogin = 1;
  625.                 SerPuts("\r\n");
  626.                 ulog(1, "Login: %s", ptr);
  627.                 break;
  628.             case ST_PASSWD:
  629.                 HavePasswd = 1;
  630.                 SerPuts("\r\n");
  631.                 ulog(2, "Password: %s", ptr);
  632.                 break;
  633.             }
  634.             break;
  635.             default:
  636.             if (Index == 31)
  637.                 break;
  638.             if (State == ST_LOGIN) {
  639.                 char cc[2];
  640.                 cc[0] = c;
  641.                 cc[1] = 0;
  642.                 SerPuts(cc);
  643.             }
  644.             ptr[Index++] = c;
  645.             break;
  646.             }
  647.         }
  648.         if (IosrIP == 0)
  649.             RxStart();
  650.         }
  651.     }
  652.     }
  653.     xexit(0);
  654. }
  655.  
  656. void
  657. RxStart()
  658. {
  659.     Iosr.IOSer.io_Data = (APTR)RxBuf;
  660.     Iosr.IOSer.io_Length = 1;
  661.     Iosr.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  662.     IosrIP = 1;
  663.     SendIO(&Iosr);
  664. }
  665.  
  666. void
  667. RxStop()
  668. {
  669.     if (IosrIP) {
  670.     AbortIO(&Iosr);
  671.     WaitIO(&Iosr);
  672.     IosrIP = 0;
  673.     }
  674. }
  675.  
  676. long
  677. GetStatus()
  678. {
  679.     int error;
  680.     long status = CIAF_COMCD;    /*  no carrier detect    */
  681.  
  682.     if (!DeviceInUse()) {
  683.     Ioss.IOSer.io_Command = SDCMD_QUERY;
  684.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  685.     if (error = DoIO(&Ioss))
  686.         ulog(0, "Query Error %d", error);
  687.     status = Ioss.io_Status;
  688.     if (IgnoreCD)
  689.         status &= ~CIAF_COMCD;
  690.     }
  691.     return(status);
  692. }
  693.  
  694. void
  695. xexit(code)
  696. {
  697.     if (ComPortMask) {
  698.     GMsg *msg;
  699.     Forbid();
  700.     while (msg = (GMsg *)GetMsg(ComPort))
  701.         ReplyMsg((MSG *)msg);
  702.     DeletePort(ComPort);
  703.     Permit();
  704.     }
  705.     if (IotIP) {
  706.     AbortIO(&Iot);
  707.     WaitIO(&Iot);
  708.     }
  709.     if (Iot.tr_node.io_Device)
  710.     CloseDevice(&Iot);
  711.  
  712.     RxStop();
  713.  
  714.     if (Ios.IOSer.io_Device) {
  715.     RestoreDeviceVector(Ios.IOSer.io_Device);
  716.     CloseDevice(&Ios);
  717.     }
  718.  
  719.     if (IoSink)
  720.     DeletePort(IoSink);
  721.  
  722.     if (NullFH)
  723.     Close(NullFH);
  724.  
  725.     if (code)
  726.     ulog(-1, "Getty Exiting with code %d", code);
  727.  
  728.     exit(code);
  729. }
  730.  
  731. void
  732. SerPuts(str)
  733. char *str;
  734. {
  735.     int error;
  736.  
  737.     if (!DeviceInUse()) {
  738.     Ioss.IOSer.io_Command = CMD_WRITE;
  739.     Ioss.IOSer.io_Data = (APTR)str;
  740.     Ioss.IOSer.io_Length = strlen(str);
  741.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  742.     if (error = DoIO(&Ioss))
  743.         ulog(0, "Write Error %d", error);
  744.     }
  745. }
  746.  
  747. static short RxDisableIP;
  748.  
  749. void
  750. RxDisable()
  751. {
  752.     RxDisableIP = IosrIP;
  753.     RxStop();
  754. }
  755.  
  756. void
  757. RxEnable()
  758. {
  759.     if (RxDisableIP && IosrIP == 0)
  760.     RxStart();
  761. }
  762.  
  763. void
  764. ClearRecv()
  765. {
  766.     int error;
  767.  
  768.     if (!DeviceInUse()) {
  769.  
  770.     Ioss.IOSer.io_Command = CMD_CLEAR;
  771.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  772.  
  773.     if (error = DoIO(&Ioss))
  774.         ulog(0, "Clear Error %d", error);
  775.  
  776.     if (IosrIP) {
  777.         AbortIO(&Iosr);
  778.         WaitIO(&Iosr);
  779.         IosrIP = 0;
  780.         RxStart();
  781.     }
  782.     }
  783. }
  784.  
  785. void
  786. ResetSP()
  787. {
  788.     int error;
  789.  
  790.     if (!DeviceInUse()) {
  791.     Ioss.IOSer.io_Command = CMD_RESET;
  792.     Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  793.  
  794.     if (error = DoIO(&Ioss))
  795.         ulog(0, "Reset Error %d", error);
  796.     }
  797. }
  798.  
  799.  
  800. void
  801. SetParams(wire7)
  802. {
  803.     int error;
  804.  
  805.     /*if (NoBugs == 0)
  806.     wire7 = Wire7;*/
  807.  
  808.     {
  809.  
  810.     RxStop();
  811.  
  812.     if (!DeviceInUse()) {
  813.         if (wire7 && Wire7)
  814.         Ios.io_SerFlags |= SERF_7WIRE;
  815.         else
  816.         Ios.io_SerFlags &= ~SERF_7WIRE;
  817.         Ios.IOSer.io_Command = SDCMD_SETPARAMS;
  818.         Ios.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  819.         if (error = DoIO(&Ios))
  820.         ulog(0, "SetParams Error %d", error);
  821.     }
  822.     }
  823. }
  824.  
  825. void
  826. Disconnect(dropdtr)
  827. {
  828.     short retry = (IgnoreDTR) ? 2 : 10;
  829.  
  830.     ulog(2, "Disconnect drop=%d", dropdtr);
  831.     HaveConnectMsg = 0;
  832.     HaveLogin    = 0;
  833.     HavePasswd    = 0;
  834.     LoginBuf[0] = 0;
  835.     PasswdBuf[0] = 0;
  836.     Index = 0;
  837.     State = ST_WAITCD;
  838.  
  839.     if (IgnoreCD == 0) {
  840.     while (dropdtr && DeviceInUse() == 0) {
  841.         short i;
  842.         long status = GetStatus();
  843.  
  844.         if (status & CIAF_COMCD)        /*  no carrier  */
  845.         break;
  846.  
  847.         RxDisable();
  848.         SetParams(0);
  849.  
  850.         if (IgnoreDTR) {
  851.         if (ModemType != 'd') {
  852.             Delay(70);
  853.             if (DeviceInUse())
  854.             break;
  855.             SerPuts("+++");
  856.             Delay(70);
  857.             if (DeviceInUse())
  858.             break;
  859.             SerPuts("\010\010\r");
  860.             Delay(10);
  861.             if (DeviceInUse())
  862.             break;
  863.             SerPuts("ATH0\r");
  864.             Delay(120);
  865.         }
  866.         } else {
  867.         RefCnt += 2;
  868.         CloseDevice(&Ios);
  869.         Ios.IOSer.io_Device = NULL;    /*  so xexit doesn't reclose */
  870.         for (i = 0; i < 5; ++i) {      /*  5 seconds   */
  871.             Delay(50);
  872.             if (SetSignal(SIGBREAKF_CTRL_C, 0) & SIGBREAKF_CTRL_C)
  873.             xexit(23);
  874.         }
  875.  
  876.         /*
  877.          *  Use Iosr to re-open serial device so we don't loose
  878.          *  our config.
  879.          */
  880.  
  881.         RefCnt -= 2;
  882.         if (Wire7)
  883.             Ios.io_SerFlags |= SERF_7WIRE;
  884.         else
  885.             Ios.io_SerFlags &= ~SERF_7WIRE;
  886.         if (OpenDevice(DeviceName, DeviceUnit, &Ios, 0)) {
  887.             Ios.IOSer.io_Device = NULL;
  888.             xexit(22);
  889.         }
  890.         Iosr.IOSer.io_Device = Ios.IOSer.io_Device;
  891.         Ioss.IOSer.io_Device = Ios.IOSer.io_Device;
  892.         Iosr.IOSer.io_Unit = Ios.IOSer.io_Unit;
  893.         Ioss.IOSer.io_Unit = Ios.IOSer.io_Unit;
  894.         SetParams(1);
  895.         }
  896.  
  897.         /*
  898.          *    Loop until carrier lost
  899.          */
  900.  
  901.         RxEnable();
  902.  
  903.         if (--retry == 0) {
  904.         if (IgnoreDTR == 0)
  905.             puts("Getty: unable to disconnect!");
  906.         break;
  907.         }
  908.     }
  909.     }
  910.     if (!DeviceInUse()) {
  911.     ResetSP();
  912.     InitModem();
  913.     }
  914. }
  915.  
  916. void
  917. InitModem()
  918. {
  919.     char buf[64];
  920.     short i;
  921.  
  922.     RxDisable();
  923.     ulog(2, "Init Modem");
  924.     Ios.io_Baud = Bauds[0];    /*  reset baud rate */
  925.     BIndex = 0;
  926.     SetParams(0);
  927.     RxEnable();
  928.  
  929.     switch(ModemType) {
  930.     case 'm':               /*  Multi Modem     */
  931.     SerPuts("\010\010\r");
  932.     Delay(10);
  933.     if (DeviceInUse())
  934.         break;
  935.     SerPuts("AT\r");
  936.     Delay(50);
  937.     if (DeviceInUse())
  938.         break;
  939.     sprintf(buf, "ATM%dS0=%dX4$BA%d&E%d\r",
  940.         SpeakerLevel,
  941.         AnswerRing,
  942.         !BaudAdjust,
  943.         (Wire7) ? 4 : 3
  944.     );
  945.     SerPuts(buf);
  946.     break;
  947.     case 'h':
  948.     SerPuts("\010\010\r");
  949.     Delay(10);
  950.     if (DeviceInUse())
  951.         break;
  952.     SerPuts("ATZ\r");
  953.     Delay(120);
  954.     if (DeviceInUse())
  955.         break;
  956.     strcpy(buf, "AT");
  957.     if (SpeakerOpt)
  958.         sprintf(buf + strlen(buf), "M%d", SpeakerLevel);
  959.     sprintf(buf + strlen(buf), "S0=%d", AnswerRing);
  960.     strcat(buf, "\r");
  961.     SerPuts(buf);
  962.     break;
  963.     case 'd':
  964.     SerPuts("\010\010\r");
  965.     break;
  966.     }
  967.     for (i = 0; i < arysize(AtFields) && AtFields[i]; ++i) {
  968.     Delay(50);
  969.     if (DeviceInUse())
  970.         break;
  971.     SerPuts(AtFields[i]);
  972.     SerPuts("\r");
  973.     }
  974.     Delay(20);
  975.     ClearRecv();
  976.     Index = 0;
  977. }
  978.  
  979. void
  980. DoOptions(ac, av)
  981. char *av[];
  982. {
  983.     short i;
  984.     short bi = 0;
  985.     short fi = 0;
  986.     long v;
  987.  
  988.     LogLevel = 1;
  989.  
  990.     for (i = 1; i < ac; ++i) {
  991.     char *ptr = av[i];
  992.     if (*ptr != '-') {
  993.         if (fi != arysize(AtFields))
  994.         AtFields[fi++] = ptr;
  995.         else
  996.         puts("AT field overflow");
  997.         continue;
  998.     }
  999.     if (*++ptr)             /*  skip -      */
  1000.         ++ptr;        /*  and option    */
  1001.     v = atoi(ptr);
  1002.     switch(ptr[-1]) {
  1003.     case '0':
  1004.         ZeroOption = 1;
  1005.         break;
  1006.     case '7':
  1007.         Wire7 = 1;
  1008.         break;
  1009.     case 'S':
  1010.         DeviceName = ptr;
  1011.         break;
  1012.     case 'U':
  1013.         DeviceUnit = v;
  1014.         break;
  1015.     case 'M':
  1016.         ModemType = *ptr;
  1017.         break;
  1018.     case 'A':
  1019.         BaudAdjust = 1;
  1020.         break;
  1021.     case 'B':
  1022.         if (bi != arysize(Bauds))
  1023.         Bauds[bi++] = v;
  1024.         else
  1025.         puts("-B field overflow");
  1026.         break;
  1027.     case 'm':
  1028.         SpeakerOpt = 1;
  1029.         SpeakerLevel = v;
  1030.         break;
  1031.     case 'r':
  1032.         AnswerRing = v;
  1033.         break;
  1034.     case 'h':
  1035.         IgnoreCD = !v;
  1036.         break;
  1037.     case 'c':
  1038.         IgnoreConnect = !v;
  1039.         break;
  1040.     case 'd':
  1041.         IgnoreDTR = !v;
  1042.         break;
  1043.     case 'x':
  1044.         LogLevel = v;
  1045.         LogToStdout = (v >= 9);
  1046.         break;
  1047.     case 'n':
  1048.         /*NoBugs = 1;*/
  1049.         break;
  1050.     default:
  1051.         printf("Warning, Bad option: -%s\n", ptr);
  1052.         break;
  1053.     }
  1054.     }
  1055.     if (fi && fi != arysize(AtFields))
  1056.     AtFields[fi] = NULL;
  1057.     if (bi && bi != arysize(Bauds))
  1058.     Bauds[bi] = 0;
  1059. }
  1060.  
  1061. DeviceInUse()
  1062. {
  1063.     return(RefCnt > 0);
  1064. }
  1065.  
  1066. /*
  1067.  *  Device Vector Intercept, used to force SERF_SHARED on device open.
  1068.  */
  1069.  
  1070. extern void AsmOpenIntercept();
  1071. extern void AsmCloseIntercept();
  1072. /*extern void A2232BeginIOFix();*/
  1073.  
  1074. FPTR OldOpenVector;
  1075. FPTR OldCloseVector;
  1076. /*FPTR OldBeginIOVector;*/
  1077.  
  1078. void
  1079. InterceptDeviceVector(dev)
  1080. struct Library *dev;
  1081. {
  1082.     Forbid();
  1083.     OldOpenVector = SetFunction((struct Library *)dev, LIB_OPEN, AsmOpenIntercept);
  1084.     OldCloseVector = SetFunction((struct Library *)dev, LIB_CLOSE, AsmCloseIntercept);
  1085.     /*OldBeginIOVector = SetFunction((struct Library *)dev, DEV_BEGINIO, A2232BeginIOFix);*/
  1086.     Permit();
  1087. }
  1088.  
  1089. void
  1090. RestoreDeviceVector(dev)
  1091. struct Library *dev;
  1092. {
  1093.     FPTR oldFunc;
  1094.     int error = 0;
  1095.  
  1096.     /*
  1097.      *    must restore in same order as had openned
  1098.      */
  1099.  
  1100.     for (;;) {
  1101.     Forbid();
  1102.     oldFunc = (FPTR)SetFunction((struct Library *)dev, LIB_OPEN, OldOpenVector);
  1103.     if (oldFunc != (FPTR)AsmOpenIntercept) {
  1104.         SetFunction((struct Library *)dev, LIB_OPEN, oldFunc);
  1105.         Permit();
  1106.         if (error == 0) {
  1107.         error = 1;
  1108.         ulog(-1, "UNABLE TO REVERSE SETVECTOR, YOU MUST DEINSTALL");
  1109.         ulog(-1, "GETTYs ON THE SAME DEVICE IN REVERSE ORDER!");
  1110.         }
  1111.         Delay(50 * 5);
  1112.         continue;
  1113.     }
  1114.     break;
  1115.     }
  1116.     SetFunction((struct Library *)dev, LIB_CLOSE, OldCloseVector);
  1117.     /*SetFunction((struct Library *)dev, DEV_BEGINIO, OldBeginIOVector);*/
  1118.     Permit();
  1119. }
  1120.  
  1121.  
  1122.